/*
 *  Copyright 2007 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.model.core;

import java.util.*;

/**
 * <p>Represents a sequence of pages/resources belonging to some
 * {@link Localizable}</p>
 * <p><a href="Sequence.java.html"><i>View source</i></a></p>
 *
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version : $Revision: 1.5 $ : 2007/12/17 13:38:25 $
 * @see com.blandware.atleap.model.core.SequenceItem
 * @struts.form include-all="false" extends="BaseForm"
 * @hibernate.class table="`al_core_sequence`" lazy="false"
 * @hibernate.cache usage="read-write"
 */
public class Sequence extends BaseObject {

    /**
     * Type that restricts sequence to contain links to pages
     */
    public static final int TYPE_PAGES = 0;

    /**
     * Type that restricts sequence to contain links to content resources
     */
    public static final int TYPE_RESOURCES = 1;

    //~ Instance fields ========================================================

    /**
     * The ID of this sequence
     */
	protected Long id;
    /**
     * The identifier of this sequence. It is unique per sequence owner.
     */
	protected String identifier;
    /**
     * Type of sequence: what can it contain
     */
	protected byte type;
    /**
     * Owner of this sequence
     */
	protected Localizable owner;
    /**
     * List of sequence items that belong to this sequence
     */
	protected List sequenceItems = new ArrayList();
    /**
     * Version of this sequence (used in optimistic locking)
     */
	protected Long version;

    //~ Methods ================================================================

	/**
	 * Returns the id.
	 *
	 * @return id
	 * @struts.form-field
	 * @hibernate.id column="`id`"
	 * generator-class="increment" unsaved-value="null"
	 */
	public Long getId() {
		return id;
	}

    /**
     * Sets the id of sequence.
     *
     * @param id new id
     */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * Returns version.
	 *
	 * @return version
	 * @struts.form-field
	 * @hibernate.version column="`version`" type="long" unsaved-value="null"
	 */
	public Long getVersion() {
		return version;
	}

    /**
     * Sets version of sequence.
     *
     * @param version new version
     */
	public void setVersion(Long version) {
		this.version = version;
	}

	/**
	 * Returns the identifier of the sequence.
	 *
	 * @return the identifier
	 * @struts.form-field
	 * @struts.validator type="required"
	 * @struts.validator-args arg0resource="core.sequence.form.identifier"
	 * @struts.validator type="mask" msgkey="core.commons.errors.sequenceIdentifier"
	 * @struts.validator-var name="mask" value="^([0-9a-zA-Z\_]+(\.|\-)?)*[0-9a-zA-Z\_]+$"
	 * @hibernate.property
	 * @hibernate.column name="`identifier`" not-null="true" unique="false" length="252"
	 */
	public String getIdentifier() {
		return identifier;
	}

    /**
     * Sets the identifier of the sequence.
     *
     * @param identifier new identifier
     */
	public void setIdentifier(String identifier) {
		this.identifier = identifier;
	}

	/**
	 * Returns the type of the sequence.
	 *
	 * @return sequence type
	 * @struts.form-field
	 * @struts.validator type="required"
	 * @hibernate.property column="`type`" not-null="true" unique="false"
	 */
	public byte getType() {
		return type;
	}

    /**
     * Sets the type of the sequence.
     *
     * @param type type to set
     */
	public void setType(byte type) {
		this.type = type;
	}

    /**
	 * Returns the localizable owner.
	 *
	 * @return a localizable
	 * @struts.form-field
	 * @hibernate.many-to-one column="`localizable_id`" not-null="true" outer-join="false" lazy="false"
	 */
	public Localizable getOwner() {
		return owner;
	}

    /**
     * Sets the localizable owner.
     *
     * @param owner the new owner
     */
	public void setOwner(Localizable owner) {
		this.owner = owner;
	}

	/**
	 * Returns the list of sequence items.
	 *
	 * @return list of sequence items
	 * @hibernate.bag name="sequenceItems" inverse="true" lazy="true" cascade="delete" outer-join="false"
	 * @hibernate.collection-key column="`sequence_id`"
	 * @hibernate.collection-one-to-many class="com.blandware.atleap.model.core.SequenceItem"
	 */
	public List getSequenceItems() {
		return sequenceItems;
	}

    /**
     * Sets the list of sequence items.
     *
     * @param sequenceItems list of sequence items
     */
	public void setSequenceItems(List sequenceItems) {
		this.sequenceItems = sequenceItems;
	}

    /**
     * Adds a sequence item to the list of items that are owned by this sequence.
     *
     * @param sequenceItem the item to be added
     */
	public void addSequenceItem(SequenceItem sequenceItem) {
		sequenceItem.setSequence(this);
		sequenceItems.add(sequenceItem);
	}

    /**
     * Updates sequence item.
     *
     * @param sequenceItem the item to be updated
     * @return old SequenceItem object
     */
	public SequenceItem updateSequenceItem(SequenceItem sequenceItem) {
        SequenceItem oldSequenceItem = null;
		if ( !sequenceItem.getSequence().equals(this) ) {
            int index = sequenceItem.getSequence().sequenceItems.indexOf(sequenceItem);
            if (index != -1) {
                oldSequenceItem = (SequenceItem)sequenceItem.getSequence().sequenceItems.remove(index);
            }
			sequenceItems.add(sequenceItem);
			sequenceItem.setSequence(this);
		}
        return oldSequenceItem;
	}

    /**
     * Removes a sequence item from the list of items that are owned by
     * this sequence.
     *
     * @param sequenceItem the item to be removed
     */
	public void removeSequenceItem(SequenceItem sequenceItem) {
		sequenceItems.remove(sequenceItem);
	}

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Sequence sequence = (Sequence) o;

        if (identifier != null ? !identifier.equals(sequence.identifier) : sequence.identifier != null)
            return false;
        if (owner != null ? !owner.equals(sequence.owner) : sequence.owner != null)
            return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = (id != null ? id.hashCode() : 0);
        result = 31 * result + (identifier != null ? identifier.hashCode() : 0);
        result = 31 * result + (owner != null ? owner.hashCode() : 0);
        result = 31 * result + (version != null ? version.hashCode() : 0);
        return result;
    }
}
